package io.github.echarts.render.series;

import io.github.echarts.model.SeriesModel;
import io.github.echarts.model.coordinate.CoordinateSystem;
import io.github.echarts.model.coordinate.DataRange;
import io.github.echarts.model.coordinate.cartesian.CartesianCoordinateSystem;
import io.github.echarts.model.coordinate.cartesian.DefaultCartesianCoordinateSystem;
import io.github.echarts.model.geometry.Rectangle;
import io.github.echarts.model.series.BarSeriesModel;
import io.github.echarts.model.series.DefaultBarSeriesModel;
import io.github.echarts.render.GraphicsRenderer;
import io.github.echarts.render.RenderContext;
import io.github.echarts.render.svg.SVGLayerType;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 条形图渲染器
 * 负责将条形图系列模型渲染为图形
 */
public class BarSeriesRenderer implements SeriesRenderer {

    private RenderContext renderContext;

    public BarSeriesRenderer() {
    }

    public void setRenderContext(RenderContext renderContext) {
        this.renderContext = renderContext;
    }

    @Override
    public void render(SeriesModel seriesModel, GraphicsRenderer renderer) {
        if (!"bar".equals(seriesModel.getType())) {
            throw new IllegalArgumentException("只能渲染条形图系列");
        }
        
        if (!(seriesModel instanceof BarSeriesModel)) {
            throw new IllegalArgumentException("需要BarSeriesModel类型");
        }
        
        BarSeriesModel barModel = (BarSeriesModel) seriesModel;
        
        // 设置渲染层级为系列层
        renderer.setCurrentLayer(SVGLayerType.SERIES);
        
        // 获取坐标系
        CoordinateSystem coordinateSystem = seriesModel.getCoordinateSystem();
        if (coordinateSystem == null) {
            // 尝试从渲染上下文中获取坐标系信息
            String coordinateSystemId = seriesModel.getCoordinateSystemId();
            
            if (renderContext == null) {
                throw new IllegalStateException("渲染上下文未设置");
            }
            
            // 使用安全方法获取坐标系信息，避免null
            RenderContext.CoordinateSystemInfo csInfo = renderContext.getCoordinateSystemInfoSafe(
                coordinateSystemId, 800, 600);
            
            // 使用坐标系信息中的区域
            Rectangle layoutArea = csInfo.getArea();
            
            // 渲染柱状图
            renderBarChart(barModel, layoutArea, renderer);
        } else if (coordinateSystem instanceof CartesianCoordinateSystem) {
            // 如果是笛卡尔坐标系，使用其布局区域
            CartesianCoordinateSystem cartesianCS = (CartesianCoordinateSystem) coordinateSystem;
            
            // 渲染柱状图
            renderBarChartWithCartesianCS(barModel, cartesianCS, renderer);
        } else {
            throw new IllegalStateException("条形图只支持笛卡尔坐标系");
        }
    }
    
    /**
     * 使用简单布局区域渲染柱状图（不依赖坐标系对象）
     * 
     * @param barModel 柱状图模型
     * @param layoutArea 布局区域
     * @param renderer 渲染器
     */
    private void renderBarChart(BarSeriesModel barModel, Rectangle layoutArea, GraphicsRenderer renderer) {
        // 获取数据
        List<Double> data = getNumericDataFromSeries(barModel);
        if (data == null || data.isEmpty()) {
            return;
        }
        
        // 计算柱子宽度和间距
        int barCount = data.size();
        int availableWidth = (int) layoutArea.getWidth();
        int barWidth = barModel.getBarWidth();
        int barGap = barModel.getBarGap();
        
        // 获取数据范围以计算高度比例
        DataRange dataRange = barModel.getDataRange();
        double minValue = dataRange.getMin();
        double maxValue = dataRange.getMax();
        double valueRange = maxValue - minValue;
        
        // 如果数值范围太小，设置一个默认值以避免除零错误
        if (valueRange < 0.00001) {
            valueRange = 1.0;
        }
        
        // 获取柱子填充颜色
        String fillColor = getBarColor(barModel);
        
        // 是否是堆叠柱状图
        boolean isStacked = barModel.isStacked();
        double[] stackedBaseline = null;
        if (isStacked && barModel instanceof DefaultBarSeriesModel) {
            stackedBaseline = ((DefaultBarSeriesModel) barModel).getStackedBaseline();
        }
        
        // 渲染每个柱子
        for (int i = 0; i < data.size(); i++) {
            double value = data.get(i);
            
            // 计算柱子高度（按照数值在范围内的比例计算）
            double valueRatio = (value - minValue) / valueRange;
            int barHeight = (int) (layoutArea.getHeight() * valueRatio);
            
            // 确保最小高度
            barHeight = Math.max(barHeight, barModel.getBarMinHeight());
            
            // 计算柱子位置
            int x = (int) (layoutArea.getX() + (i * availableWidth / barCount) + (availableWidth / barCount - barWidth) / 2);
            
            // 在模型坐标系统中，Y轴向上为正，原点在左下角
            // 柱子应该从底部开始，向上绘制
            int yBottom = (int) (layoutArea.getY() + layoutArea.getHeight());
            
            // 如果是堆叠柱状图，调整Y坐标
            if (isStacked && stackedBaseline != null && i < stackedBaseline.length) {
                double baselineRatio = (stackedBaseline[i] - minValue) / valueRange;
                int baselineHeight = (int) (layoutArea.getHeight() * baselineRatio);
                yBottom -= baselineHeight;
            }
            
            // 计算柱子顶部的Y坐标
            int y = yBottom - barHeight;
            

            
            // 绘制柱子 - 使用对象式API
            renderer.drawRect(x, y, barWidth, barHeight, true, fillColor, null);
        }
    }
    
    /**
     * 使用笛卡尔坐标系渲染柱状图
     * 
     * @param barModel 柱状图模型
     * @param cartesianCS 笛卡尔坐标系
     * @param renderer 渲染器
     */
    private void renderBarChartWithCartesianCS(BarSeriesModel barModel, CartesianCoordinateSystem cartesianCS, GraphicsRenderer renderer) {
        if (!(cartesianCS instanceof DefaultCartesianCoordinateSystem)) {
            // 简化实现，仅支持DefaultCartesianCoordinateSystem
            renderBarChart(barModel, cartesianCS.getLayoutArea(), renderer);
            return;
        }
        
        DefaultCartesianCoordinateSystem cs = (DefaultCartesianCoordinateSystem) cartesianCS;
        
        // 获取数据
        List<Double> data = getNumericDataFromSeries(barModel);
        if (data == null || data.isEmpty()) {
            return;
        }
        
        // 获取柱子填充颜色
        String fillColor = getBarColor(barModel);
        
        // 是否是堆叠柱状图
        boolean isStacked = barModel.isStacked();
        double[] stackedBaseline = null;
        if (isStacked && barModel instanceof DefaultBarSeriesModel) {
            stackedBaseline = ((DefaultBarSeriesModel) barModel).getStackedBaseline();
        }
        
        // 获取柱状图配置
        int barWidth = barModel.getBarWidth();
        int barMinHeight = barModel.getBarMinHeight();
        
        // 渲染每个柱子
        for (int i = 0; i < data.size(); i++) {
            double value = data.get(i);
            
            // 使用坐标系获取位置
            double x = cs.getCategoryPositionXByIndex(i) - barWidth / 2.0;
            
            // 计算基准位置（非堆叠情况下是0）
            double baseline = 0;
            if (isStacked && stackedBaseline != null && i < stackedBaseline.length) {
                baseline = stackedBaseline[i];
            }
            
            // 计算顶部Y坐标
            double y;
            double height;
            
            if (value >= 0) {
                // 正值柱子（向上）
                y = cs.getValuePositionY(baseline + value);
                height = cs.getValuePositionY(baseline) - y;
            } else {
                // 负值柱子（向下）
                y = cs.getValuePositionY(baseline);
                height = cs.getValuePositionY(baseline + value) - y;
            }
            
            // 确保最小高度
            height = Math.max(height, barMinHeight);
            
            // 绘制柱子 - 使用对象式API
            renderer.drawRect((int)x, (int)y, barWidth, (int)height, true, fillColor, null);
        }
    }

    /**
     * 从系列模型中获取数值数据
     *
     * @param seriesModel 系列模型
     * @return 数值数据列表
     */
    private List<Double> getNumericDataFromSeries(SeriesModel seriesModel) {
        // 获取系列数据
        List<Object> rawData = seriesModel.getData();
        if (rawData == null || rawData.isEmpty()) {
            return new ArrayList<>();
        }
        
        // 尝试将Object转换为Double
        List<Double> numericData = new ArrayList<>();
        for (Object item : rawData) {
            if (item instanceof Number) {
                numericData.add(((Number) item).doubleValue());
            } else if (item instanceof String) {
                try {
                    numericData.add(Double.parseDouble((String) item));
                } catch (NumberFormatException e) {
                    // 忽略无法转换的数据
                }
            } else if (item instanceof Map) {
                try {
                    @SuppressWarnings("unchecked")
                    Object value = ((Map<String, Object>) item).get("value");
                    if (value instanceof Number) {
                        numericData.add(((Number) value).doubleValue());
                    } else if (value instanceof String) {
                        numericData.add(Double.parseDouble((String) value));
                    }
                } catch (Exception e) {
                    // 忽略无法转换的数据
                }
            }
        }
        
        return numericData;
    }
    
    /**
     * 获取条形图颜色
     *
     * @param seriesModel 系列模型
     * @return 颜色字符串
     */
    private String getBarColor(SeriesModel seriesModel) {
        if (seriesModel instanceof DefaultBarSeriesModel) {
            return ((DefaultBarSeriesModel) seriesModel).getColor();
        }
        return "#5470c6"; // 默认蓝色
    }

    @Override
    public String getSupportedSeriesType() {
        return "bar";
    }
} 